package main

import (
	"fmt"
	"strconv"
)

// You are a developer for a university. Your current project is to develop a system for students to find courses they share with friends. The university has a system for querying courses students are enrolled in, returned as a list of (ID, course) pairs.
// Write a function that takes in a list of (student ID number, course name) pairs and returns, for every pair of students, a list of all courses they share.

// Sample Input:

// student_course_pairs_1 = [
//   ["58", "Software Design"],
//   ["58", "Linear Algebra"],
//   ["94", "Art History"],
//   ["94", "Operating Systems"],
//   ["17", "Software Design"],
//   ["58", "Mechanics"],
//   ["58", "Economics"],
//   ["17", "Linear Algebra"],
//   ["17", "Political Science"],
//   ["94", "Economics"],
//   ["25", "Economics"],
// ]

// Sample Output (pseudocode, in any order):
// 58
// 94
// 17
// 25

// find_pairs(student_course_pairs_1) =>
// {
//   [58, 17]: ["Software Design", "Linear Algebra"]
//   [58, 94]: ["Economics"]
//   [58, 25]: ["Economics"]
//   [94, 25]: ["Economics"]
//   [17, 94]: []
//   [17, 25]: []
// }

// Additional test cases:

// Sample Input:

// student_course_pairs_2 = [
//   ["42", "Software Design"],
//   ["0", "Advanced Mechanics"],
//   ["9", "Art History"],
// ]

// Sample output:

// find_pairs(student_course_pairs_2) =>
// {
//   [0, 42]: []
//   [0, 9]: []
//   [9, 42]: []
// }

// map: sid -> [courses]
// unique id array

func findPairs(studentCoursePairs [][]string) map[[2]int][]string {
	res := make(map[[2]int][]string)
	studentIds := []int{}
	// sid : [<courses>]
	studentCourses := make(map[int][]string)
	for _, pair := range studentCoursePairs {
		studentId, _ := strconv.Atoi(pair[0])
		studentCourse := pair[1]

		if _, ok := studentCourses[studentId]; ok == false {
			// not in the map
			studentCourses[studentId] = []string{studentCourse}
			studentIds = append(studentIds, studentId)
		} else {
			studentCourses[studentId] = append(studentCourses[studentId], studentCourse)
		}
	}
	// [58 94 17 25]
	// map[17:[Software Design Linear Algebra Political Science] 25:[Economics] 58:[Software Design Linear Algebra Mechanics Economics] 94:[Art History Operating Systems Economics]]
	// fmt.Println(studentCourses)
	studentIdPairs := getStudentPairs(studentIds)
	//[[58 94] [58 17] [58 25] [94 17] [94 25] [17 25]]
	for _, pair := range studentIdPairs {
		overlappedCourses := overlappingCourses(studentCourses[pair[0]], studentCourses[pair[1]])
		res[pair] = overlappedCourses
	}
	return res
}

func getStudentPairs(students []int) [][2]int {
	res := [][2]int{}
	for i := 0; i < len(students)-1; i++ {
		for j := i + 1; j < len(students); j++ {
			pair := [2]int{students[i], students[j]}
			res = append(res, pair)
		}
	}
	return res
}

func overlappingCourses(courses1, courses2 []string) []string {
	res := []string{}
	m := make(map[string]bool)

	for _, course := range courses1 {
		m[course] = true
	}

	for _, course := range courses2 {
		if _, ok := m[course]; ok == true {
			res = append(res, course)
		}
	}

	return res
}

func main() {
	// input := [][]string{
	// 	[]string{"58", "Software Design"},
	// 	[]string{"58", "Linear Algebra"},
	// 	[]string{"94", "Art History"},
	// 	[]string{"94", "Operating Systems"},
	// 	[]string{"17", "Software Design"},
	// 	[]string{"58", "Mechanics"},
	// 	[]string{"58", "Economics"},
	// 	[]string{"17", "Linear Algebra"},
	// 	[]string{"17", "Political Science"},
	// 	[]string{"94", "Economics"},
	// 	[]string{"25", "Economics"},
	// }
	input2 := [][]string{
		[]string{"42", "Software Design"},
		[]string{"0", "Advanced Mechanics"},
		[]string{"9", "Art History"},
	}
	fmt.Println(findPairs(input2))

	// input2 := []int{58, 94, 17, 25}
	// fmt.Println(getStudentPairs(input2))
}
